/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.setting.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.message.SendContextType;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.util.StringUtil;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.message.vo.EmailInfo;
import com.je.message.vo.EmailMsg;
import com.je.meta.controller.setting.model.MyAuthenticator;
import com.je.meta.service.setting.MetaSystemSettingService;
import com.je.meta.setting.ConfigItem;
import com.je.meta.setting.PlatformSystemConfig;
import com.je.meta.setting.SettingException;
import com.je.meta.setting.SystemSetting;
import com.je.meta.setting.develop.NoteServiceSystemConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.*;

@Service
public class MetaSystemSettingServiceImpl implements MetaSystemSettingService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;

    /**
     * 全局系统配置
     */
    private static final PlatformSystemConfig GLOBAL_PLATFORM_CONFIG = new PlatformSystemConfig();

    @Override
    public SystemSetting findAllSetting() {
        return GLOBAL_PLATFORM_CONFIG;
    }

    /**
     * 加载系统变量
     */
    @Override
    public void reloadLoadSystemSetting() {
        List<DynaBean> sysVars = metaService.select("JE_CORE_SETTING", null);
        SystemSetting findedSetting;
        String attribute;
        for (DynaBean sysVar : sysVars) {
            attribute = sysVar.getStr("ATTRIBUTE");
            findedSetting = GLOBAL_PLATFORM_CONFIG.findChildSetting(attribute, "");
            if (findedSetting == null) {
                continue;
            }
            findedSetting.addItem(sysVar.getStr("CODE"), null, sysVar.getStr("VALUE"), null);
            //TODO 放入缓存
        }
    }

    /**
     * 更新系统设置(系统设置页面保存使用)
     *
     * @param attribute 安全设置、消息推送
     * @param map       值
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doWriteSysConfigVariables(String attribute, JSONObject map, String type) throws SettingException {
        SystemSetting setting = GLOBAL_PLATFORM_CONFIG.findChildSetting(attribute, type);
        if (setting == null) {
            throw new SettingException("Can't find the system setting!");
        }
        List<String> itemKeys = setting.getItemKeys();
        List<DynaBean> sysVars = metaService.select("JE_CORE_SETTING", ConditionsWrapper.builder()
                .eq("ATTRIBUTE", attribute));

        //查找需要更新的配置
        List<DynaBean> updatedBeans = new ArrayList<>();
        List<String> insertedKeys = new ArrayList<>();
        List<String> remove = new ArrayList<>();

        //过滤key
//        boolean isHave = false;
//        for(String key:map.keySet()){
//            isHave = false;
//            for (String eachKey : itemKeys) {
//                if(eachKey.equals(key)){
//                    isHave = true;
//                    break;
//                }
//            }
//            if(!isHave){
//                remove.add(key);
//            }
//        }
//
//        for (String key:remove) {
//            map.remove(key);
//        }

        //修改key数组
        for (String key : map.keySet()) {
            DynaBean findedBean = null;
            for (DynaBean sysVar : sysVars) {
                if (key.equals(sysVar.getStr("CODE"))) {
                    findedBean = sysVar;
                    break;
                }
            }
            if (findedBean != null) {
                updatedBeans.add(findedBean);
            }
        }

        //新添key数组
        for (String eachKey : itemKeys) {
            DynaBean findedBean = null;
            for (DynaBean sysVar : sysVars) {
                if (eachKey.equals(sysVar.getStr("CODE"))) {
                    findedBean = sysVar;
                    break;
                }
            }
            if (findedBean == null) {
                insertedKeys.add(eachKey);
            }
        }

        //更新需要更新的配置
        for (DynaBean eachBean : updatedBeans) {
            String value = map.getString(eachBean.getStr("CODE"));
            eachBean.set("VALUE", value);
            metaService.update(eachBean);
        }
        //插入需要插入的配置
        DynaBean eachInsertBean;
        for (String eachKey : insertedKeys) {
            eachInsertBean = new DynaBean("JE_CORE_SETTING", false);
            eachInsertBean.set("CODE", eachKey);
            eachInsertBean.set("ATTRIBUTE", attribute);
            eachInsertBean.set("SY_ORDERINDEX", "0");
            eachInsertBean.set("SY_STATUS", "");
            if(map.get(eachKey) instanceof JSONArray){
                JSONArray jsonArray = (JSONArray) map.get(eachKey);
                eachInsertBean.set("VALUE", jsonArray.toJSONString());
            }else {
                eachInsertBean.set("VALUE", map.get(eachKey));
            }
            commonService.buildModelCreateInfo(eachInsertBean);
            metaService.insert(eachInsertBean);
        }

    }

    @Override
    public void doWriteSettingValue(String attribute, String code, String value) {
        DynaBean valueBean = metaService.selectOne("JE_CORE_SETTING", ConditionsWrapper.builder()
                .eq("ATTRIBUTE", attribute)
                .eq("CODE", code));
        if (valueBean != null) {
            valueBean.set("VALUE", value);
            metaService.update(valueBean);
        } else {
            valueBean = new DynaBean("JE_CORE_SETTING", false);
            valueBean.set("CODE", code);
            valueBean.set("VALUE", value);
            valueBean.set("ATTRIBUTE", attribute);
            metaService.insert(valueBean);
        }
    }

    @Override
    public SystemSetting findSystemConfig(String attribute) {
        SystemSetting setting = GLOBAL_PLATFORM_CONFIG.findChildSetting(attribute, "");
        Set<ConfigItem> items = setting.getItems();
        Set<SystemSetting> childSettings = setting.getChildSettings();
        if (null != items) {
            List<DynaBean> sysVars = metaService.select("JE_CORE_SETTING", ConditionsWrapper.builder()
                    .eq("ATTRIBUTE", attribute));
            Iterator iter = items.iterator();
            while (iter.hasNext()) {
                ConfigItem item = (ConfigItem) iter.next();
                for (DynaBean sysVar : sysVars) {
                    if (item.getCode().equals(sysVar.getStr("CODE"))) {
                        item.setValue(sysVar.getStr("VALUE"));
                        break;
                    }
                }
            }
        }

        if (null != childSettings) {
            for (SystemSetting childSetting : childSettings) {
                findSystemConfig(childSetting.getCode());
            }
        }
        return setting;
    }

    @Override
    public EmailInfo getEmailInfo() {
        EmailInfo emailInfo = new EmailInfo();
        emailInfo.setAddress(findSettingValue("JE_SYS_EMAIL_USERNAME"));
        return emailInfo;
    }

    @Override
    public void sendeEmail(EmailMsg msgVo, EmailInfo emailInfo) throws Exception {
        // 判断是否需要身份认证
        MyAuthenticator authenticator = null;
        Properties pro = buildEmailConfig(emailInfo);
        String password = findSettingValue("JE_SYS_EMAIL_PASSWORD");
        if (emailInfo != null) {
            authenticator = new MyAuthenticator(emailInfo.getAddress(), password);
        } else {
            if ("1".equals(findSettingValue("JE_SYS_EMAIL_SERVERVALIDATE"))) {
                //如果需要身份认证，则创建一个密码验证器
                String userName = findSettingValue("JE_SYS_EMAIL_USERNAME");
                if (StringUtil.isEmpty(userName) || StringUtil.isEmpty(password)) {
                    throw new PlatformException("邮箱发送未提供帐号密码异常!", PlatformExceptionEnum.JE_MESSAGE_EMAIL_NOUSERNAME_ERROR, new Object[]{msgVo, emailInfo});
                }
                authenticator = new MyAuthenticator(userName, password);
            }
        }

        // 根据邮件会话属性和密码验证器构造一个发送邮件的session
        Session sendMailSession = Session.getInstance(pro, authenticator);
        // 根据session创建一个邮件消息
        Message mailMessage = new MimeMessage(sendMailSession);
        String title = findSettingValue("JE_SYS_EMAIL_SENDTITLE");
        String sendAddress = "";
        if (emailInfo != null) {
            sendAddress = emailInfo.getAddress();
            InternetAddress from = new InternetAddress(sendAddress);
            if (StringUtil.isNotEmpty(title)) {
                from.setPersonal(title);
            }
            mailMessage.setFrom(from);
        } else {
            // 创建邮件发送者地址
            InternetAddress from = new InternetAddress(sendAddress);
            if (StringUtil.isNotEmpty(title)) {
                from.setPersonal(title);
            }
            // 设置邮件消息的发送者
            mailMessage.setFrom(from);
        }

        if (emailInfo != null) {
            sendAddress = emailInfo.getAddress();
            InternetAddress from = new InternetAddress(sendAddress);
            if (StringUtil.isNotEmpty(title)) {
                from.setPersonal(title);
            }
            mailMessage.setFrom(from);
        } else {
            // 创建邮件发送者地址
            InternetAddress from = new InternetAddress(sendAddress);
            if (StringUtil.isNotEmpty(title)) {
                from.setPersonal(title);
            }
            // 设置邮件消息的发送者
            mailMessage.setFrom(from);
        }
        // 创建邮件的接收者地址，并设置到邮件消息中
        String receiveEmail = msgVo.getReceiveEmail();
        //如果是外部邮件发送
        if (emailInfo != null) {
            InternetAddress[] to = buildAddress(msgVo.getReceiveEmail());
            mailMessage.setRecipients(Message.RecipientType.TO, to);
        } else {
            if (receiveEmail.split(",").length > 1) {
                InternetAddress[] to = InternetAddress.parse(receiveEmail);
                mailMessage.setRecipients(Message.RecipientType.TO, to);
            } else {
                Address to = new InternetAddress(msgVo.getReceiveEmail());
                mailMessage.setRecipient(Message.RecipientType.TO, to);
            }
        }
        //设置紧急状态
        //默认紧急状态为普通
        String faster = "3";
        if ("1".equals(msgVo.getFaster())) {
            faster = "1";
        }
        mailMessage.setHeader("X-Priority", faster);
        if ("1".equals(msgVo.getReplySign())) {
            mailMessage.setHeader("Disposition-Notification-To", sendAddress);
        }

        // 设置邮件消息的主题
        String sj = msgVo.getSubject();
        mailMessage.setSubject(sj);
        // 设置邮件消息发送的时间
        mailMessage.setSentDate(new Date());
        String contextType = "text/html";//纯文本
        if (SendContextType.TEXT.equals(msgVo.getContextType())) {
            contextType = "text/plain"; //超文本
        }
        // MiniMultipart类是一个容器类，包含MimeBodyPart类型的对象
        Multipart mainPart = new MimeMultipart();
        // 创建一个包含内容的MimeBodyPart
        MimeBodyPart mbp = new MimeBodyPart();
        // 设置HTML内容
        mbp.setContent(msgVo.getContext(), contextType + "; charset=utf-8");
        mainPart.addBodyPart(mbp);
        // 将MiniMultipart对象设置为邮件内容
        mailMessage.setContent(mainPart);
        // 发送邮件
        Transport.send(mailMessage);
    }

    @Override
    public List<Map<String, String>> getMessageType() throws Exception {
        List<Map<String, String>> result = new ArrayList();
        SystemSetting systemSetting = findSystemConfig(NoteServiceSystemConfig.MESSAGE_TYPE);
        Set<ConfigItem> items = systemSetting.getItems();
        List<ConfigItem> list = new ArrayList(items);
        Collections.sort(list);
        String push_platform = findSettingValue("JE_PUSH_PLATFORM");
        String[] messageTypes = push_platform.split(",");
        for (ConfigItem configItem : list) {
            Map<String, String> push = new HashMap<>();
            if (!Strings.isNullOrEmpty(configItem.getType())) {
                for (String messageType : messageTypes) {
                    if (configItem.getType().equals(messageType)) {
                        push.put("label", configItem.getText());
                        push.put("value", configItem.getType());
                        result.add(push);
                    }
                }
            }
        }
        return result;
    }

    private Properties buildEmailConfig(EmailInfo emailInfo) {
        Properties p = new Properties();

        String auth = findSettingValue("JE_SYS_EMAIL_SERVERVALIDATE");
        if (emailInfo != null) {
            //是否启用ssl
            if (!"0".equals(emailInfo.getSmtpSsl())) {
                p.put("mail.smtp.ssl.enable", findSettingValue("MAIL_SMTP_SSL_ENABLE"));
                p.put("mail.smtp.socketFactory.class", findSettingValue("MAIL_SMTP_SOCKETFACTORY_CLASS"));
            }
            if (StringUtil.isNotEmpty(emailInfo.getSendAuth()) && "0".equals(emailInfo.getSendAuth())) {
                auth = "false";
            }
        } else {
            //是否启用ssl
            if (!"0".equals(findSettingValue("JE_SYS_EMAIL_SSL"))) {
                p.put("mail.smtp.ssl.enable", findSettingValue("MAIL_SMTP_SSL_ENABLE"));
                p.put("mail.smtp.socketFactory.class", findSettingValue("MAIL_SMTP_SOCKETFACTORY_CLASS"));
            }
            auth = "1".equals(findSettingValue("JE_SYS_EMAIL_SERVERVALIDATE")) ? "true" : "false";
        }
        p.put("mail.smtp.host", findSettingValue("JE_SYS_EMAIL_SERVERHOST"));
        p.put("mail.smtp.port", findSettingValue("JE_SYS_EMAIL_SERVERPORT"));
        p.put("mail.smtp.auth", auth);

        return p;
    }

    private InternetAddress[] buildAddress(String sjrStr) throws Exception {
        if (StringUtil.isNotEmpty(sjrStr)) {
            JSONArray arrays = JSONArray.parseArray(sjrStr);
            InternetAddress[] ias = new InternetAddress[arrays.size()];
            for (int i = 0; i < arrays.size(); i++) {
                JSONObject infos = arrays.getJSONObject(i);
                InternetAddress to = new InternetAddress(infos.getString("code"));
                to.setPersonal(infos.getString("text"));
                ias[i] = to;
            }
            return ias;
        } else {
            return null;
        }
    }

    public String findSettingValue(String code) {
        DynaBean valueBean = metaService.selectOne("JE_CORE_SETTING", ConditionsWrapper.builder()
                .eq("CODE", code));
        if (null == valueBean) {
            return null;
        }
        return valueBean.getStr("VALUE");
    }

}
